move xml tag utilities to xml_tag.cc (#960)
authortsteven4 <13596209+tsteven4@users.noreply.github.com>
Tue, 27 Dec 2022 13:34:03 +0000 (06:34 -0700)
committerGitHub <noreply@github.com>
Tue, 27 Dec 2022 13:34:03 +0000 (06:34 -0700)
* move xml tag utilities to xml_tag.cc

they are already declared in src/core/xmltag.h

* move xml_tag.cc to src/core, where it's h file is.

* move global xml_tag routines into class.

* make xml_next non-static.

* make xml_findnext non-static.

* make xml_findfirst non-static

* make xml_attribute non-static

* eliminate some shadowing

* rename XmlTag class.

* retire fs_xml_alloc.

* use QStringView with XmlTag.

* back off QStringView for xml_attribute for Qt 5.

CMakeLists.txt
gpx.cc
gpx.h
html.cc
kml.cc
src/core/xmltag.cc [new file with mode: 0644]
src/core/xmltag.h
text.cc
util.cc
xmltag.cc [deleted file]

index 2a2b6fd635ce9328fcb1b892a0aa2a925e0e3cbd..caecf0c762209335cfbed60a1bc14d29ea4887c9 100644 (file)
@@ -189,6 +189,7 @@ set(SUPPORT
   src/core/usasciicodec.cc
   src/core/vector3d.cc
   src/core/xmlstreamwriter.cc
+  src/core/xmltag.cc
   strptime.c
   units.cc
   util.cc
@@ -196,7 +197,6 @@ set(SUPPORT
   vecs.cc
   waypt.cc
   xmlgeneric.cc
-  xmltag.cc
 )
 if(${QT_VERSION_MAJOR} EQUAL "6")
   set(SUPPORT ${SUPPORT} src/core/codecdevice.cc)
diff --git a/gpx.cc b/gpx.cc
index 05e64e66da9a7f50037d3f5f81adff9a8aa6722b..f671f42b8e0e4794e42d89094f97497a9a555277 100644 (file)
--- a/gpx.cc
+++ b/gpx.cc
@@ -218,7 +218,7 @@ GpxFormat::start_something_else(QStringView el, const QXmlStreamAttributes& attr
     return;
   }
 
-  auto* new_tag = new xml_tag;
+  auto* new_tag = new XmlTag;
   new_tag->tagname = el.toString();
 
   const QXmlStreamNamespaceDeclarations ns = reader->namespaceDeclarations();
@@ -262,7 +262,7 @@ GpxFormat::start_something_else(QStringView el, const QXmlStreamAttributes& attr
       cur_tag->sibling = new_tag;
       new_tag->parent = nullptr;
     } else {
-      fs_xml* new_fs_gpx = fs_xml_alloc(kFsGpx);
+      auto* new_fs_gpx = new fs_xml(kFsGpx);
       new_fs_gpx->tag = new_tag;
       fs_ptr->FsChainAdd(new_fs_gpx);
       new_tag->parent = nullptr;
@@ -901,7 +901,7 @@ GpxFormat::gpx_cdata(QStringView s)
   }
 
   if (cur_tag->child) {
-    xml_tag* tmp_tag = cur_tag->child;
+    XmlTag* tmp_tag = cur_tag->child;
     while (tmp_tag->sibling) {
       tmp_tag = tmp_tag->sibling;
     }
@@ -1138,7 +1138,7 @@ GpxFormat::write_attributes(const QXmlStreamAttributes& attributes) const
 }
 
 void
-GpxFormat::fprint_xml_chain(xml_tag* tag, const Waypoint* wpt) const
+GpxFormat::fprint_xml_chain(XmlTag* tag, const Waypoint* wpt) const
 {
   while (tag) {
     writer->writeStartElement(tag->tagname);
diff --git a/gpx.h b/gpx.h
index cc8baa75b8d19a9761d63772126e1ea9d802013e..98f68b0e7a9b2e4b48cf49fe245277cfefb564f2 100644 (file)
--- a/gpx.h
+++ b/gpx.h
@@ -204,7 +204,7 @@ private:
   void gpx_end(QStringView unused);
   void gpx_cdata(QStringView s);
   void write_attributes(const QXmlStreamAttributes& attributes) const;
-  void fprint_xml_chain(xml_tag* tag, const Waypoint* wpt) const;
+  void fprint_xml_chain(XmlTag* tag, const Waypoint* wpt) const;
   void write_gpx_url(const UrlList& urls) const;
   void write_gpx_url(const Waypoint* waypointp) const;
   void write_gpx_url(const route_head* rh) const;
@@ -225,7 +225,7 @@ private:
   void gpx_write_bounds();
 
   QXmlStreamReader* reader{};
-  xml_tag* cur_tag{};
+  XmlTag* cur_tag{};
   QString cdatastr;
   char* opt_logpoint = nullptr;
   char* opt_humminbirdext = nullptr;
diff --git a/html.cc b/html.cc
index 19cebca0174b89fc7cf94d349ea502dea5fe8499..17ea6455321f677cf95b5ef366565fe50c014390 100644 (file)
--- a/html.cc
+++ b/html.cc
@@ -147,25 +147,25 @@ HtmlFormat::html_disp(const Waypoint* wpt) const
   if (includelogs) {
     const auto* fs_gpx = reinterpret_cast<fs_xml*>(wpt->fs.FsChainFind(kFsGpx));
     if (fs_gpx && fs_gpx->tag) {
-      xml_tag* root = fs_gpx->tag;
-      xml_tag* curlog = xml_findfirst(root, "groundspeak:log");
+      XmlTag* root = fs_gpx->tag;
+      XmlTag* curlog = root->xml_findfirst(u"groundspeak:log");
       while (curlog) {
         time_t logtime = 0;
         *file_out << "          <p class=\"gpsbabellog\">\n";
 
-        xml_tag* logpart = xml_findfirst(curlog, "groundspeak:type");
+        XmlTag* logpart = curlog->xml_findfirst(u"groundspeak:type");
         if (logpart) {
           *file_out << "<span class=\"gpsbabellogtype\">"
                     << logpart->cdata << "</span> by ";
         }
 
-        logpart = xml_findfirst(curlog, "groundspeak:finder");
+        logpart = curlog->xml_findfirst(u"groundspeak:finder");
         if (logpart) {
           *file_out << "<span class=\"gpsbabellogfinder\">"
                     << logpart->cdata.toHtmlEscaped() << "</span> on ";
         }
 
-        logpart = xml_findfirst(curlog, "groundspeak:date");
+        logpart = curlog->xml_findfirst(u"groundspeak:date");
         if (logpart) {
           logtime = xml_parse_time(logpart->cdata).toTime_t();
           struct tm* logtm = localtime(&logtime);
@@ -177,17 +177,17 @@ HtmlFormat::html_disp(const Waypoint* wpt) const
           }
         }
 
-        logpart = xml_findfirst(curlog, "groundspeak:log_wpt");
+        logpart = curlog->xml_findfirst(u"groundspeak:log_wpt");
         if (logpart) {
-          double lat = xml_attribute(logpart->attributes, "lat").toDouble();
-          double lon = xml_attribute(logpart->attributes, "lon").toDouble();
+          double lat = logpart->xml_attribute("lat").toDouble();
+          double lon = logpart->xml_attribute("lon").toDouble();
           *file_out << "<span class=\"gpsbabellogcoords\">"
                     << pretty_deg_format(lat, lon, degformat[2], " ", true) << "</span><br>\n";
         }
 
-        logpart = xml_findfirst(curlog, "groundspeak:text");
+        logpart = curlog->xml_findfirst(u"groundspeak:text");
         if (logpart) {
-          QString encstr = xml_attribute(logpart->attributes, "encoded");
+          QString encstr = logpart->xml_attribute("encoded");
           bool encoded = !encstr.startsWith('F', Qt::CaseInsensitive);
 
           QString s;
@@ -201,7 +201,7 @@ HtmlFormat::html_disp(const Waypoint* wpt) const
         }
 
         *file_out << "</p>\n";
-        curlog = xml_findnext(root, curlog, "groundspeak:log");
+        curlog = curlog->xml_findnext(root, u"groundspeak:log");
       }
     }
   }
diff --git a/kml.cc b/kml.cc
index 9dbe69c4fed0c12a843f5497dc94c7884ff9624f..2e92632002d348da3d87ca07d8e4279982f756e0 100644 (file)
--- a/kml.cc
+++ b/kml.cc
@@ -1213,22 +1213,22 @@ QString KmlFormat::kml_geocache_get_logs(const Waypoint* wpt) const
     return r;
   }
 
-  xml_tag* root = fs_gpx->tag;
-  xml_tag* curlog = xml_findfirst(root, "groundspeak:log");
+  XmlTag* root = fs_gpx->tag;
+  XmlTag* curlog = root->xml_findfirst(u"groundspeak:log");
   while (curlog) {
     // Unless we have a broken GPX input, these logparts
     // branches will always be taken.
-    xml_tag* logpart = xml_findfirst(curlog, "groundspeak:type");
+    XmlTag* logpart = curlog->xml_findfirst(u"groundspeak:type");
     if (logpart) {
       r = r + "<p><b>" + logpart->cdata + "</b>";
     }
 
-    logpart = xml_findfirst(curlog, "groundspeak:finder");
+    logpart = curlog->xml_findfirst(u"groundspeak:finder");
     if (logpart) {
       r = r + " by " + logpart->cdata;
     }
 
-    logpart = xml_findfirst(curlog, "groundspeak:date");
+    logpart = curlog->xml_findfirst(u"groundspeak:date");
     if (logpart) {
       gpsbabel::DateTime t = xml_parse_time(logpart->cdata);
       if (t.isValid()) {
@@ -1236,14 +1236,14 @@ QString KmlFormat::kml_geocache_get_logs(const Waypoint* wpt) const
       }
     }
 
-    logpart = xml_findfirst(curlog, "groundspeak:text");
+    logpart = curlog->xml_findfirst(u"groundspeak:text");
     if (logpart) {
       r += "<br />";
       r += logpart->cdata.toHtmlEscaped();
     }
 
     r += "</p>";
-    curlog = xml_findnext(root, curlog, "groundspeak:log");
+    curlog = curlog->xml_findnext(root, u"groundspeak:log");
   }
   return r;
 }
diff --git a/src/core/xmltag.cc b/src/core/xmltag.cc
new file mode 100644 (file)
index 0000000..2376bce
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+    Functions to deal with xml_tags
+
+    Copyright (C) 2005 Ron Parker and Robert Lipe.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ */
+
+#include <QString>                      // for QString
+#include <QStringView>                  // for QStringView
+#include <Qt>                           // for CaseInsensitive
+#include <QXmlStreamAttribute>          // for QXmlStreamAttribute
+#include <QXmlStreamAttributes>         // for QXmlStreamAttributes
+
+#include "src/core/xmltag.h"
+
+
+/*
+ * xml_tag utilities
+ */
+
+XmlTag* XmlTag::xml_next(const XmlTag* root)
+{
+  XmlTag* cur = this;
+  if (cur->child) {
+    cur = cur->child;
+  } else if (cur->sibling) {
+    cur = cur->sibling;
+  } else {
+    cur = cur->parent;
+    if (cur == root) {
+      cur = nullptr;
+    }
+    if (cur) {
+      cur = cur->sibling;
+    }
+  }
+  return cur;
+}
+
+XmlTag* XmlTag::xml_findnext(const XmlTag* root, QStringView name)
+{
+  XmlTag* result = this;
+  do {
+    result = result->xml_next(root);
+  } while (result && result->tagname.compare(name, Qt::CaseInsensitive));
+  return result;
+}
+
+XmlTag* XmlTag::xml_findfirst(QStringView name)
+{
+  return xml_findnext(this, name);
+}
+
+QString XmlTag::xml_attribute(const QString& attrname) const
+{
+  for (const auto& attribute : this->attributes) {
+    if (attribute.qualifiedName().compare(attrname, Qt::CaseInsensitive) == 0) {
+      return attribute.value().toString();
+    }
+  }
+  return QString();
+}
+
+static void
+free_xml_tag(XmlTag* tag)
+{
+  while (tag) {
+    if (tag->child) {
+      free_xml_tag(tag->child);
+    }
+
+    XmlTag* next = tag->sibling;
+    delete tag;
+    tag = next;
+  }
+}
+
+// FIXME: at some point, this becomes a plain ole copy constructor.
+static void
+copy_xml_tag(XmlTag** copy, XmlTag* src, XmlTag* parent)
+{
+  if (!src) {
+    *copy = nullptr;
+    return;
+  }
+
+  auto* res = new XmlTag;
+  *copy = res;
+
+  res->tagname = (src->tagname);
+  res->cdata = (src->cdata);
+  res->parentcdata = (src->parentcdata);
+  res->attributes = src->attributes;
+  res->parent = parent;
+  copy_xml_tag(&(res->sibling), src->sibling, parent);
+  copy_xml_tag(&(res->child), src->child, res);
+}
+
+fs_xml::~fs_xml()
+{
+  free_xml_tag(tag);
+}
+
+fs_xml* fs_xml::clone() const
+{
+  auto* copy = new fs_xml(*this);
+  copy_xml_tag(&(copy->tag), tag, nullptr);
+  return copy;
+}
index 6e276a161632b95ac1acae6835e0ddd15ca70572..4eb6fb963ef818cfb99389f07d0b7df36d530a22 100644 (file)
 #ifndef SRC_CORE_XMLTAG_H
 #define SRC_CORE_XMLTAG_H
 
-#include <QString>                                 // for QString
-#include <QXmlStreamAttributes>                    // for QXmlStreamAttributes
+#include <QString>               // for QString
+#include <QStringView>           // for QStringView
+#include <QXmlStreamAttributes>  // for QXmlStreamAttributes
 
-#include "defs.h"
+#include "formspec.h"            // for FormatSpecificData, FsType
 
-class xml_tag
+
+class XmlTag
 {
 public:
+
+  /* Member Functions */
+
+  XmlTag* xml_findnext(const XmlTag* root, QStringView name);
+  XmlTag* xml_findfirst(QStringView name);
+  QString xml_attribute(const QString& attrname) const;
+
+  /* Data Members */
+
   QString tagname;
   QString cdata;
   QString parentcdata;
   QXmlStreamAttributes attributes;
-  xml_tag* parent{nullptr};
-  xml_tag* sibling{nullptr};
-  xml_tag* child{nullptr};
-};
+  XmlTag* parent{nullptr};
+  XmlTag* sibling{nullptr};
+  XmlTag* child{nullptr};
 
-xml_tag* xml_findfirst(xml_tag* root, const QString& tagname);
-xml_tag* xml_findnext(xml_tag* root, xml_tag* cur, const QString& tagname);
-QString xml_attribute(const QXmlStreamAttributes& attributes, const QString& attrname);
+private:
+
+  /* Member Functions */
+
+  XmlTag* xml_next(const XmlTag* root);
+};
 
 struct fs_xml : FormatSpecificData {
   explicit fs_xml(FsType type) : FormatSpecificData(type) {}
@@ -52,9 +65,6 @@ public:
 
   fs_xml* clone() const override;
 
-  xml_tag* tag{nullptr};
+  XmlTag* tag{nullptr};
 };
-
-fs_xml* fs_xml_alloc(FsType type);
-
 #endif // SRC_CORE_XMLTAG_H
diff --git a/text.cc b/text.cc
index 6b83635451eb50ef894af5dbab88d67c2b8353a4..2dd985160d79b10a3f04dbe32cc4925e01000f30 100644 (file)
--- a/text.cc
+++ b/text.cc
@@ -130,23 +130,23 @@ TextFormat::text_disp(const Waypoint* wpt)
   if (includelogs) {
     const auto* fs_gpx = reinterpret_cast<fs_xml*>(wpt->fs.FsChainFind(kFsGpx));
     if (fs_gpx && fs_gpx->tag) {
-      xml_tag* root = fs_gpx->tag;
-      xml_tag* curlog = xml_findfirst(root, "groundspeak:log");
+      XmlTag* root = fs_gpx->tag;
+      XmlTag* curlog = root->xml_findfirst(u"groundspeak:log");
       while (curlog) {
         time_t logtime = 0;
         *file_out << "\n";
 
-        xml_tag* logpart = xml_findfirst(curlog, "groundspeak:type");
+        XmlTag* logpart = curlog->xml_findfirst(u"groundspeak:type");
         if (logpart) {
           *file_out << logpart->cdata << " by ";
         }
 
-        logpart = xml_findfirst(curlog, "groundspeak:finder");
+        logpart = curlog->xml_findfirst(u"groundspeak:finder");
         if (logpart) {
           *file_out << logpart->cdata << " on ";
         }
 
-        logpart = xml_findfirst(curlog, "groundspeak:date");
+        logpart = curlog->xml_findfirst(u"groundspeak:date");
         if (logpart) {
           logtime = xml_parse_time(logpart->cdata).toTime_t();
           struct tm* logtm = localtime(&logtime);
@@ -158,16 +158,16 @@ TextFormat::text_disp(const Waypoint* wpt)
           }
         }
 
-        logpart = xml_findfirst(curlog, "groundspeak:log_wpt");
+        logpart = curlog->xml_findfirst(u"groundspeak:log_wpt");
         if (logpart) {
-          double lat = xml_attribute(logpart->attributes, "lat").toDouble();
-          double lon = xml_attribute(logpart->attributes, "lon").toDouble();
+          double lat = logpart->xml_attribute("lat").toDouble();
+          double lon = logpart->xml_attribute("lon").toDouble();
           *file_out << pretty_deg_format(lat, lon, degformat[2], " ", false) << "\n";
         }
 
-        logpart = xml_findfirst(curlog, "groundspeak:text");
+        logpart = curlog->xml_findfirst(u"groundspeak:text");
         if (logpart) {
-          QString encstr = xml_attribute(logpart->attributes, "encoded");
+          QString encstr = logpart->xml_attribute("encoded");
           bool encoded = !encstr.startsWith('F', Qt::CaseInsensitive);
 
           QString s;
@@ -181,7 +181,7 @@ TextFormat::text_disp(const Waypoint* wpt)
         }
 
         *file_out << "\n";
-        curlog = xml_findnext(root, curlog, "groundspeak:log");
+        curlog = curlog->xml_findnext(root, u"groundspeak:log");
       }
     }
   }
diff --git a/util.cc b/util.cc
index b343a0dda898dbd4861c374a94a28173e354697b..5b7ab0ce2386a2eace83c7e494165046bb330d73 100644 (file)
--- a/util.cc
+++ b/util.cc
@@ -22,6 +22,7 @@
 #include <algorithm>                    // for sort
 #include <cctype>                       // for isspace, isalpha, ispunct, tolower, toupper
 #include <cerrno>                       // for errno
+#include <climits>                      // for INT_MAX, INT_MIN
 #include <cmath>                        // for fabs, floor
 #include <cstdarg>                      // for va_list, va_end, va_start, va_copy
 #include <cstdio>                       // for size_t, vsnprintf, FILE, fopen, printf, sprintf, stderr, stdin, stdout
@@ -32,6 +33,7 @@
 
 #include <QByteArray>                   // for QByteArray
 #include <QChar>                        // for QChar, operator<=, operator>=
+#include <QDate>                        // for QDate
 #include <QDateTime>                    // for QDateTime
 #include <QFileInfo>                    // for QFileInfo
 #include <QList>                        // for QList
 #include <QTextBoundaryFinder>          // for QTextBoundaryFinder, QTextBoundaryFinder::Grapheme
 #include <QTextCodec>                   // for QTextCodec
 #include <QTextStream>                  // for operator<<, QTextStream, qSetFieldWidth, endl, QTextStream::AlignLeft
-#include <QXmlStreamAttribute>          // for QXmlStreamAttribute
-#include <QXmlStreamAttributes>         // for QXmlStreamAttributes
 #include <Qt>                           // for CaseInsensitive
+#include <QTime>                        // for QTime
 #include <QTimeZone>                    // for QTimeZone
 #include <QtGlobal>                     // for qAsConst, qEnvironmentVariableIsSet, QAddConst<>::Type, qPrintable
 
 #include "defs.h"
 #include "src/core/datetime.h"          // for DateTime
 #include "src/core/logging.h"           // for Warning
-#include "src/core/xmltag.h"            // for xml_tag, xml_attribute, xml_findfirst, xml_findnext
+
 
 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
 # define i_am_little_endian 0
@@ -1344,52 +1345,6 @@ strip_html(const utf_string* in)
 #endif
 }
 
-/*
- * xml_tag utilities
- */
-
-xml_tag* xml_next(xml_tag* root, xml_tag* cur)
-{
-  if (cur->child) {
-    cur = cur->child;
-  } else if (cur->sibling) {
-    cur = cur->sibling;
-  } else {
-    cur = cur->parent;
-    if (cur == root) {
-      cur = nullptr;
-    }
-    if (cur) {
-      cur = cur->sibling;
-    }
-  }
-  return cur;
-}
-
-xml_tag* xml_findnext(xml_tag* root, xml_tag* cur, const QString& tagname)
-{
-  xml_tag* result = cur;
-  do {
-    result = xml_next(root, result);
-  } while (result && result->tagname.compare(tagname, Qt::CaseInsensitive));
-  return result;
-}
-
-xml_tag* xml_findfirst(xml_tag* root, const QString& tagname)
-{
-  return xml_findnext(root, root, tagname);
-}
-
-QString xml_attribute(const QXmlStreamAttributes& attributes, const QString& attrname)
-{
-  for (const auto& attribute : attributes) {
-    if (attribute.qualifiedName().compare(attrname, Qt::CaseInsensitive) == 0) {
-      return attribute.value().toString();
-    }
-  }
-  return QString();
-}
-
 QString get_filename(const QString& fname)
 {
   return QFileInfo(fname).fileName();
diff --git a/xmltag.cc b/xmltag.cc
deleted file mode 100644 (file)
index d01594d..0000000
--- a/xmltag.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-    Functions to deal with xml_tags
-
-    Copyright (C) 2005 Ron Parker and Robert Lipe.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
- */
-
-#include <QString>                      // for QString
-#include <QXmlStreamAttributes>         // for QXmlStreamAttributes
-
-#include "defs.h"
-#include "src/core/xmltag.h"
-
-static void
-free_xml_tag(xml_tag* tag)
-{
-  while (tag) {
-    if (tag->child) {
-      free_xml_tag(tag->child);
-    }
-
-    xml_tag* next = tag->sibling;
-    delete tag;
-    tag = next;
-  }
-}
-
-// FIXME: at some point, this becomes a plain ole copy constructor.
-static void
-copy_xml_tag(xml_tag** copy, xml_tag* src, xml_tag* parent)
-{
-  if (!src) {
-    *copy = nullptr;
-    return;
-  }
-
-  auto* res = new xml_tag;
-  *copy = res;
-
-  res->tagname = (src->tagname);
-  res->cdata = (src->cdata);
-  res->parentcdata = (src->parentcdata);
-  res->attributes = src->attributes;
-  res->parent = parent;
-  copy_xml_tag(&(res->sibling), src->sibling, parent);
-  copy_xml_tag(&(res->child), src->child, res);
-}
-
-fs_xml::~fs_xml()
-{
-  free_xml_tag(tag);
-}
-
-fs_xml* fs_xml::clone() const
-{
-  auto* copy = new fs_xml(*this);
-  copy_xml_tag(&(copy->tag), tag, nullptr);
-  return copy;
-}
-
-fs_xml* fs_xml_alloc(FsType type)
-{
-  auto* result = new fs_xml(type);
-  return result;
-}